home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Mac Game Programming Gurus / TricksOfTheMacGameProgrammingGurus.iso / More Source / C⁄C++ / CModalProgress 1.1 / CModalProgress.cp next >
Text File  |  1995-02-18  |  19KB  |  665 lines

  1. //
  2. //    CModalProgress.cp
  3. //    
  4. //    This file contains the definition information for the CModalProgress class.
  5. //    This class provides an interface for displaying to the user, a visual 
  6. //    indication to the progress of a time intensive task.
  7. //
  8. //    History
  9. //    -------
  10. //    
  11. //    Graham Heathcote, 1st of September 1994.
  12. //        -    Creation of initial version 1.0 release
  13. //
  14. //    Graham Heathcote, 5th of February 1995.
  15. //        -    Fixed problem with B/W rendering of progress bar. Needed to change from setting
  16. //            fore colour to setting back colour in the DrawStdBarIndicator method.
  17. //        -    Converted the procedure pointers to UniversalProcPtr for use with PowerPC compilers.
  18. //
  19. //    Graham Heathcote, 16th of February 1995.
  20. //        -    Added the SetParamText() method and the extra SetupDialog() method.
  21. //        -    Added the CanProcessEvent() method which lets the main application pass in an
  22. //            event for the dialog to process if it can.
  23. //        -    Added the ProcessIdle() method to use when processing events by the main application.
  24. //
  25. //    Version 1.1
  26. //    
  27. //    Copyright 1994, 1995 Alysoft Solutions. All rights reserved.
  28. //
  29.  
  30. #ifndef __QUICKDRAW__
  31. #include <Quickdraw.h>
  32. #endif
  33.  
  34. #include "CModalProgress.h"
  35.  
  36. // ---------------------------------------------------------------------------
  37. //        • Local Prototypes
  38. // ---------------------------------------------------------------------------
  39.  
  40. pascal void DrawBar(WindowPtr theWindow, short itemNumber) ;
  41. pascal void DrawButtonRect(WindowPtr theWindow, short itemNumber) ;
  42.  
  43. // ---------------------------------------------------------------------------
  44. //        • CModalProgress
  45. // ---------------------------------------------------------------------------
  46.  
  47. CModalProgress::CModalProgress()
  48. {    
  49.     fDialog = NULL ;
  50.     fCurrentPercent = 0.0 ;
  51.     fStartStatePercent = 0.0 ;
  52.     fCurrentStateSpacePercent = 0.0 ;
  53.     fInfiniteDrawDelay = kDefaultInfiniteDrawDelay ;
  54.     fPercentText = fProgressBar = fInfiniteBar = false ;
  55.     fPercentTextItem = fProgressBarItem = fInfiniteBarItem = 0 ;
  56.     fPercentTextDeltaLimit = 1 ;
  57.     fButtonOutlineDrawProc = NewUserItemProc(DrawButtonRect) ;
  58.     fProgressBarDrawProc = NewUserItemProc(DrawBar) ;
  59. }
  60.  
  61. // ---------------------------------------------------------------------------
  62. //        • ~CModalProgress
  63. // ---------------------------------------------------------------------------
  64. //    Destructor. Delete the dialog structure if it is still around
  65.  
  66. CModalProgress::~CModalProgress()
  67. {
  68.     if (fDialog)
  69.         DisposeDialog(fDialog) ;
  70.     
  71.     DisposeRoutineDescriptor(fButtonOutlineDrawProc) ;
  72.     DisposeRoutineDescriptor(fProgressBarDrawProc) ;
  73. }
  74.  
  75. // ---------------------------------------------------------------------------
  76. //        • SetParamText
  77. // ---------------------------------------------------------------------------
  78. //    Set the param text items in the dialog
  79.  
  80. void CModalProgress::SetParamText()
  81. {
  82.     ParamText("\p", "\p", "\p", "\p") ;
  83. }
  84.  
  85. // ---------------------------------------------------------------------------
  86. //        • SetupDialog
  87. // ---------------------------------------------------------------------------
  88. //    Set the dialog parameters
  89.  
  90. short CModalProgress::CreateTheDialog(short dlgResId)
  91. {
  92.     short                        itemType ;
  93.     Handle                        theItem ;
  94.     Rect                        box ;
  95.     short                        err = noErr ;
  96.     
  97.     fDialog = GetNewDialog(dlgResId, NULL, (WindowPtr)-1L) ;
  98.     if (fDialog)
  99.     {
  100.         SetWRefCon((WindowPtr)fDialog, (long)this) ;
  101.         
  102.         GetDialogItem(fDialog, kDefaultButtonOutlineIndex, &itemType, &theItem, &box) ;
  103.         if (itemType == userItem)
  104.         {
  105.             SetDialogItem(fDialog, kDefaultButtonOutlineIndex, itemType, (Handle)fButtonOutlineDrawProc, &box) ;
  106.         }
  107.     }
  108.     else
  109.         err = ResError() ;
  110.     
  111.     return err ;
  112. }
  113.  
  114. short CModalProgress::SetupDialog(short dlgResId)
  115. {
  116.     SetParamText() ;
  117.     
  118.     return CreateTheDialog(dlgResId) ;
  119. }
  120.  
  121. short CModalProgress::SetupDialog(short dlgResId, ConstStr255Param param0, ConstStr255Param param1, ConstStr255Param param2, ConstStr255Param param3)
  122. {
  123.     ParamText(param0, param1, param2, param3) ;
  124.     
  125.     return CreateTheDialog(dlgResId) ;
  126. }
  127.  
  128. // ---------------------------------------------------------------------------
  129. //        • SetProgressBar
  130. // ---------------------------------------------------------------------------
  131. //    Set parameters for using the standard progress bar
  132.  
  133. void CModalProgress::SetProgressBar(short dlgItem)
  134. {
  135.     short                        itemType ;
  136.     Handle                        theItem ;
  137.     Rect                        box ;
  138.  
  139.     GetDialogItem(fDialog, dlgItem, &itemType, &theItem, &box) ;
  140.     if (itemType == userItem)
  141.     {
  142.         fProgressBar = true ;
  143.         fProgressBarItem = dlgItem ;
  144.         SetDialogItem(fDialog, fProgressBarItem, itemType, (Handle)fProgressBarDrawProc, &box) ;
  145.     }
  146.     else
  147.     {
  148.         fProgressBar = false ;
  149.         fProgressBarItem = 0 ;
  150.     }
  151. }
  152.  
  153. // ---------------------------------------------------------------------------
  154. //        • SetInfiniteBar
  155. // ---------------------------------------------------------------------------
  156. //    Set parameters for using the infinite progress bar
  157.  
  158. void CModalProgress::SetInfiniteBar(short dlgItem)
  159. {
  160.     short                        itemType ;
  161.     Handle                        theItem ;
  162.     Rect                        box ;
  163.  
  164.     GetDialogItem(fDialog, dlgItem, &itemType, &theItem, &box) ;
  165.     if (itemType == userItem)
  166.     {
  167.         fInfiniteBar = true ;
  168.         fInfiniteBarItem = dlgItem ;
  169.         SetDialogItem(fDialog, fInfiniteBarItem, itemType, (Handle)fProgressBarDrawProc, &box) ;
  170.     }
  171.     else
  172.     {
  173.         fInfiniteBar = false ;
  174.         fInfiniteBarItem = 0 ;
  175.     }
  176. }
  177.  
  178. // ---------------------------------------------------------------------------
  179. //        • SetPercentText
  180. // ---------------------------------------------------------------------------
  181. //    Set parameters for using the textual percent indicator
  182.  
  183. void CModalProgress::SetPercentText(short dlgItem, short deltaLimit)
  184. {
  185.     short                        itemType ;
  186.     Handle                        theItem ;
  187.     Rect                        box ;
  188.  
  189.     GetDialogItem(fDialog, dlgItem, &itemType, &theItem, &box) ;
  190.     if ((theItem != NULL) && (itemType == statText))
  191.     {
  192.         fPercentText = true ;
  193.         fPercentTextItem = dlgItem ;
  194.         fPercentTextDeltaLimit = deltaLimit ;
  195.     }
  196.     else
  197.     {
  198.         fPercentText = false ;
  199.         fPercentTextItem = 0 ;
  200.         fPercentTextDeltaLimit = 0 ;
  201.     }
  202. }
  203.  
  204. // ---------------------------------------------------------------------------
  205. //        • UpdateProgressIndicator
  206. // ---------------------------------------------------------------------------
  207. //    Force a redraw of the progress indicator(s)
  208.  
  209. void CModalProgress::UpdateProgressIndicator(float newPercent)
  210. {
  211.     GrafPtr                        oldPort ;
  212.  
  213.     GetPort(&oldPort) ;
  214.     SetPort((GrafPtr)fDialog) ;
  215.     DrawProgressIndicator(newPercent, kIndicatorContent) ;
  216.     SetPort(oldPort) ;
  217. }
  218.  
  219. // ---------------------------------------------------------------------------
  220. //        • SetCurrentState
  221. // ---------------------------------------------------------------------------
  222. //    Set the current progress state
  223.  
  224. void CModalProgress::SetCurrentState(float statePercent)
  225. {
  226.  
  227.     fCurrentPercent = fStartStatePercent + fCurrentStateSpacePercent ;
  228.     UpdateProgressIndicator(fCurrentPercent) ;
  229.     fStartStatePercent = fCurrentPercent ;
  230.  
  231.     fCurrentStateSpacePercent = statePercent - fStartStatePercent ;
  232.     fCurrentStateSpace = 0 ;
  233.     fCurrentStateValue = 0 ;
  234. }
  235.  
  236. // ---------------------------------------------------------------------------
  237. //        • SetStateSpace
  238. // ---------------------------------------------------------------------------
  239. //    Set the resolution of the current state
  240.  
  241. void CModalProgress::SetStateSpace(float space)
  242. {
  243.     fCurrentStateSpace = space ;
  244. }
  245.  
  246. // ---------------------------------------------------------------------------
  247. //        • SetCurrentStateValue
  248. // ---------------------------------------------------------------------------
  249. //    Set the current position in this state
  250.  
  251. short CModalProgress::SetCurrentStateValue(float value)
  252. {
  253.     float                        currentPercent ;
  254.     
  255.     fCurrentStateValue = value ;
  256.     currentPercent = (fCurrentStateSpacePercent / fCurrentStateSpace) * fCurrentStateValue ;
  257.  
  258.     fCurrentPercent = currentPercent + fStartStatePercent ;
  259.     UpdateProgressIndicator(fCurrentPercent) ;
  260.     
  261.     if (fCurrentStateValue < fCurrentStateSpace)
  262.         return kStateSpaceWithinLimit ;
  263.     else
  264.         return kStateSpaceExceedingLimit ;
  265. }
  266.  
  267. // ---------------------------------------------------------------------------
  268. //        • BeginModal
  269. // ---------------------------------------------------------------------------
  270. //    Set the Modal Dialog process
  271.  
  272. void CModalProgress::BeginModal()
  273. {
  274.     fInfiniteDrawTime = TickCount() + fInfiniteDrawDelay ;
  275.     ShowWindow((WindowPtr)fDialog) ;
  276.     DrawDialog(fDialog) ;
  277. }
  278.  
  279. // ---------------------------------------------------------------------------
  280. //        • FlashButton
  281. // ---------------------------------------------------------------------------
  282. //    Flash the indicated button
  283.  
  284. Boolean CModalProgress::FlashButton(DialogPtr theDialog, short buttonIndex)
  285. {
  286.     Rect                        aRect ;
  287.     ControlHandle                theItem ;
  288.     short                        itemType ;
  289.     long                        delayTime ;
  290.     Boolean                        retVal = false ;
  291.     
  292.     GetDialogItem(theDialog, buttonIndex, &itemType, (Handle*)&theItem, &aRect) ;
  293.     if (itemType == (btnCtrl + ctrlItem))
  294.     {
  295.         if ((**theItem).contrlHilite != 255)   /* is it enabled ? */
  296.         {
  297.             HiliteControl(theItem, 1) ;
  298.             Delay(6, &delayTime) ;
  299.             HiliteControl(theItem, 0) ;
  300.             
  301.             retVal = true ;
  302.         }
  303.     }
  304.  
  305.     return retVal ;
  306. }
  307.  
  308. // ---------------------------------------------------------------------------
  309. //        • ProcessEvent
  310. // ---------------------------------------------------------------------------
  311. //    Process the event from ProcessModal()
  312. //
  313.  
  314. Boolean CModalProgress::ProcessEvent(EventRecord *theEvent, short *result)
  315. {
  316.     Boolean                    usedEvent = FALSE ;
  317.     
  318.     *result = kDialogContinues ;
  319.  
  320.     switch(theEvent->what)
  321.     {
  322.         case updateEvt:
  323.             BeginUpdate((WindowPtr)fDialog) ;
  324.             DrawDialog(fDialog) ;
  325.             EndUpdate((WindowPtr)fDialog) ;
  326.             usedEvent = TRUE ;
  327.             break ;
  328.  
  329.         case mouseDown:
  330.             WindowPtr            theWindow ;
  331.             Rect                aRect ;
  332.             short                thePart ;
  333.             
  334.             thePart = FindWindow(theEvent->where, &theWindow) ;
  335.             switch (thePart)
  336.             {
  337.                 case inDrag:
  338.                     if (theWindow == (WindowPtr)fDialog)
  339.                     {
  340.                         aRect = qd.screenBits.bounds ;
  341.                         InsetRect(&aRect, -4, -4) ;
  342.                         DragWindow(theWindow, theEvent->where, &aRect) ;
  343.                         usedEvent = TRUE ;
  344.                     }
  345.                     break ;
  346.  
  347.                 case inContent:
  348.                     if (theWindow == (WindowPtr)fDialog)
  349.                     {
  350.                         ControlHandle                    control ;
  351.                         GrafPtr                            oldPort ;
  352.                         short                            itemType ;
  353.                         Rect                            box ;
  354.                         ControlHandle                    theItem ;
  355.                         
  356.                         GetPort(&oldPort) ;
  357.                         SetPort((GrafPtr)fDialog) ;
  358.                         GlobalToLocal(&theEvent->where) ;
  359.                         SetPort(oldPort) ;
  360.                         if (FindControl(theEvent->where, (WindowPtr)fDialog, &control))
  361.                         {
  362.                             if (TrackControl(control, theEvent->where, NULL))
  363.                             {
  364.                                 GetDialogItem(fDialog, ok, &itemType, (Handle*)&theItem, &box) ;
  365.                                 if (control == theItem)
  366.                                     *result = kDialogOKHit ;
  367.                                 else
  368.                                     *result = kDialogCancelHit ;
  369.                             }
  370.                         }
  371.                     
  372.                         usedEvent = TRUE ;
  373.                     }
  374.                     break ;
  375.  
  376.                 case inMenuBar:
  377.                     break ;
  378.                 
  379.             }
  380.             break ;
  381.         
  382.         case keyDown:
  383.             short                keyCode ;
  384.  
  385.             if (FrontWindow() == (WindowRef)fDialog)
  386.             {
  387.                 keyCode = BitAnd(theEvent->message, charCodeMask) ;
  388.                 switch (keyCode)
  389.                 {
  390.                     case 46:    /* . */
  391.                         usedEvent = TRUE ;
  392.                         if ((theEvent->modifiers & cmdKey) != cmdKey)
  393.                             break ;
  394.                     
  395.                     case 27:    /* Escape */
  396.                         usedEvent = TRUE ;
  397.                         if (FlashButton(fDialog, cancel))
  398.                             *result = kDialogCancelHit ;
  399.                         break ;
  400.                     
  401.                     case 13:    /* CR */
  402.                     case 3:        /* ENTER */
  403.                         usedEvent = TRUE ;
  404.                         if (FlashButton(fDialog, ok))
  405.                             *result = kDialogOKHit ;
  406.                         break ;
  407.                 }
  408.             }
  409.             break ;
  410.     }
  411.     
  412.     return usedEvent ;
  413. }
  414.  
  415. // ---------------------------------------------------------------------------
  416. //        • ProcessIdle
  417. // ---------------------------------------------------------------------------
  418. //    Idle if we have no events occuring, needed for infinite bar.
  419.  
  420. short CModalProgress::ProcessIdle()
  421. {
  422.     short                result = kDialogContinues ;
  423.     
  424.     if (fInfiniteBar)
  425.     {
  426.         if (TickCount() > fInfiniteDrawTime)
  427.             UpdateProgressIndicator(fCurrentPercent) ;
  428.     }
  429.  
  430.     if (fCurrentPercent >= 100)
  431.         result = kDialogExceeding100pc ;
  432.  
  433.     return result ;
  434. }
  435.  
  436. // ---------------------------------------------------------------------------
  437. //        • ProcessModal
  438. // ---------------------------------------------------------------------------
  439. //    Do the general dialog processing
  440.  
  441. short CModalProgress::ProcessModal()
  442. {
  443.     EventRecord                    theEvent ;
  444.     Boolean                        ok ;
  445.     short                        result = kDialogContinues ;
  446.  
  447.     ok = GetNextEvent(everyEvent, &theEvent) ;
  448.     if (ok)
  449.         ProcessEvent(&theEvent, &result) ;
  450.  
  451.     if (result == kDialogContinues)
  452.         result = ProcessIdle() ;
  453.  
  454.     return result ;
  455. }
  456.  
  457. // ---------------------------------------------------------------------------
  458. //        • CanProcessEvent
  459. // ---------------------------------------------------------------------------
  460. //    Pass an event to the dialog and let it process it if possible. Returning TRUE
  461. //    if the event was used, FALSE if it was not.
  462.  
  463. Boolean CModalProgress::CanProcessEvent(EventRecord *theEvent, short *result)
  464. {
  465.     Boolean                        usedEvent ;
  466.  
  467.     usedEvent = ProcessEvent(theEvent, result) ;
  468.     
  469.     if (*result == kDialogContinues)
  470.         ProcessIdle() ;
  471.         
  472.     return usedEvent ;
  473. }
  474.  
  475. // ---------------------------------------------------------------------------
  476. //        • EndModal
  477. // ---------------------------------------------------------------------------
  478. //    Finished with the modal dialog
  479.  
  480. void CModalProgress::EndModal()
  481. {
  482.     FlushEvents(everyEvent, everyEvent) ;
  483.     HideWindow((WindowPtr)fDialog) ;
  484. }
  485.  
  486. // ---------------------------------------------------------------------------
  487. //        • DrawProgressIndicator
  488. // ---------------------------------------------------------------------------
  489. //    Draw the appropriate dialog items
  490.  
  491. void CModalProgress::DrawProgressIndicator(float percent, short part)
  492. {
  493.     if (fPercentText)
  494.         DrawPercentIndicator(percent, fPercentTextDeltaLimit, fPercentTextItem, part) ;
  495.     
  496.     if (fProgressBar)
  497.         DrawStdBarIndicator(percent, fProgressBarItem, part) ;
  498.     
  499.     if (fInfiniteBar)
  500.     {
  501.         if ((part & kIndicatorOutline) == kIndicatorOutline)
  502.             DrawInfiniteBarIndicator(percent, fInfiniteBarItem, part) ;
  503.         else
  504.         if (TickCount() > fInfiniteDrawTime)
  505.         {
  506.             fInfiniteDrawTime = TickCount() + fInfiniteDrawDelay ;
  507.             DrawInfiniteBarIndicator(percent, fInfiniteBarItem, part) ;
  508.         }
  509.     }
  510. }
  511.  
  512. // ---------------------------------------------------------------------------
  513. //        • DrawPercentIndicator
  514. // ---------------------------------------------------------------------------
  515.  
  516. void CModalProgress::DrawPercentIndicator(float percent, short deltaLimit, short itemIndex, short part)
  517. {
  518.     short                            itemType ;
  519.     Handle                            item ;
  520.     Rect                            box ;
  521.     Str255                            theText ;
  522.     long                            theNum ;
  523.     long                            percentLong ;
  524.     
  525.     GetDialogItem(fDialog, itemIndex, &itemType, &item, &box) ;
  526.     
  527.     GetIText(item, theText) ;
  528.     StringToNum(theText, &theNum) ;
  529.     percentLong = percent ;
  530.  
  531.     if (((percentLong - theNum) >= deltaLimit) &&
  532.         (percentLong > 0) )
  533.     {
  534.         NumToString(percentLong, theText) ;
  535.         SetIText(item, theText) ;
  536.     }
  537. }
  538.  
  539. // ---------------------------------------------------------------------------
  540. //        • DrawStdBarIndicator
  541. // ---------------------------------------------------------------------------
  542.  
  543. void CModalProgress::DrawStdBarIndicator(float percent, short itemIndex, short part)
  544. {
  545.     short                            itemType ;
  546.     Handle                            item ;
  547.     Rect                            box ;
  548.     static short                    previousRight = 0 ;
  549.     RGBColor                        barColor = {0x4444, 0x4444, 0x4444} ;
  550.     RGBColor                        emptyBarColor = {0xCCCC, 0xCCCC, 0xFFFF} ;
  551.     RGBColor                        currentForeColor ;
  552.     RGBColor                        currentBackColor ;
  553.     
  554.     GetDialogItem(fDialog, itemIndex, &itemType, &item, &box) ;
  555.     
  556.     //    Draw the frame of the progress indicator
  557.  
  558.     if ((part & kIndicatorOutline) == kIndicatorOutline)
  559.     {
  560.         //    Colour in the purple interior of the progress indicatorbar
  561.         
  562.         GetBackColor(¤tBackColor) ;
  563.         RGBBackColor(&emptyBarColor) ;
  564.         EraseRect(&box) ;
  565.         RGBBackColor(¤tBackColor) ;
  566.  
  567.         //    Draw the black frame around the outside
  568.         
  569.         FrameRect(&box) ;
  570.         previousRight = box.left + 1 ;        //    Ensure the entire body is drawn
  571.     }
  572.  
  573.     //    Draw the body of the progress indicator
  574.     
  575.     if ((part & kIndicatorContent) == kIndicatorContent)
  576.     {
  577.         InsetRect(&box, 1, 1) ;
  578.         box.right = box.left + ((float)(box.right - box.left) * (percent / 100.0)) ;
  579.         if (box.right > previousRight)
  580.         {
  581.             if (previousRight > 0)
  582.                 box.left = previousRight ;
  583.             previousRight = box.right ;
  584.             
  585.             GetForeColor(¤tForeColor) ;
  586.             RGBForeColor(&barColor) ;
  587.             PaintRect(&box) ;
  588.             RGBForeColor(¤tForeColor) ;
  589.         }
  590.     }
  591. }
  592.  
  593. // ---------------------------------------------------------------------------
  594. //        • DrawInfiniteBarIndicator
  595. // ---------------------------------------------------------------------------
  596.  
  597. void CModalProgress::DrawInfiniteBarIndicator(float percent, short itemIndex, short part)
  598. {
  599.     short                            itemType ;
  600.     Handle                            item ;
  601.     Rect                            box ;
  602.     static short                    originOffset = 0 ;
  603.     PixPatHandle                    thePattern ;
  604.     
  605.     GetDialogItem(fDialog, itemIndex, &itemType, &item, &box) ;
  606.  
  607.     //    Draw the outline of the progress indicator
  608.     
  609.     if ((part & kIndicatorOutline) == kIndicatorOutline)
  610.     {
  611.         FrameRect(&box) ;
  612.     }
  613.  
  614.     //    Draw the body of the indicator
  615.     
  616.     InsetRect(&box, 1, 1) ;
  617.     OffsetRect(&box, 0, originOffset) ;
  618.     thePattern = GetPixPat(kInfinitePaternResID) ;
  619.     PenPixPat(thePattern) ;
  620.     SetOrigin(0, originOffset) ;
  621.     PaintRect(&box) ;
  622.     
  623.     SetOrigin(0, 0) ;
  624.     PenNormal() ;
  625.  
  626.     //    Increment the origin offset if we have just been asked to draw the Content ONLY
  627.  
  628.     if (part == kIndicatorContent)
  629.         originOffset = (originOffset + 1) % ((((**(**thePattern).patMap).rowBytes) & 0xEFFF) * 8) ;
  630.  
  631.     DisposePixPat(thePattern) ;
  632. }
  633.  
  634.  
  635. // ---------------------------------------------------------------------------
  636. //        • Non-Class routines
  637. // ---------------------------------------------------------------------------
  638.  
  639. // ---------------------------------------------------------------------------
  640. //        • DawBar
  641. // ---------------------------------------------------------------------------
  642.  
  643. pascal void DrawBar(WindowPtr theWindow, short itemNumber)
  644. {
  645.     CModalProgress                    *theDialog ;
  646.     
  647.     theDialog = (CModalProgress*)GetWRefCon(theWindow) ;
  648.     theDialog->DrawProgressIndicator(theDialog->fCurrentPercent, kIndicatorOutline | kIndicatorContent) ;
  649. }
  650.  
  651. // ---------------------------------------------------------------------------
  652. //        • DrawButtonRect
  653. // ---------------------------------------------------------------------------
  654.  
  655. pascal void DrawButtonRect(WindowPtr theWindow, short itemNumber)
  656. {
  657.     Rect                            theRect ;
  658.     short                            itemType ;
  659.     Handle                            theItem ;
  660.  
  661.     GetDialogItem((DialogPtr)theWindow, itemNumber, &itemType, &theItem, &theRect) ;
  662.     PenSize(3, 3) ;
  663.     FrameRoundRect(&theRect, 16, 16) ;
  664.     PenNormal() ;
  665. }